import { Module, NestModule, MiddlewareConsumer, RequestMethod } from '@nestjs/common'
import { ConfigModule, ConfigService } from '@nestjs/config'
import envConfig from '../config/env'
import { TypeOrmModule } from '@nestjs/typeorm'
import { AppController } from './app.controller'
import { AppService } from './app.service'
import { UserModule } from './user/user.module'
import { RoleModule } from './role/role.module'
import { AuthModule } from './auth/auth.module'
import { RedisModule } from './redis/redis.module'
import { JwtAuthGuard } from 'src/auth/jwt-auth.guard'
import { RoleGuard } from 'src/auth/role.guard'
import { AuthMiddlewareMiddleware } from './auth-middleware/auth-middleware.middleware'
import { JwtModule } from '@nestjs/jwt'
import { MenuModule } from './menu/menu.module';

//自定义提供者 工厂提供者
const jwtModule = JwtModule.registerAsync({
  inject: [ConfigService],
  useFactory: (configService: ConfigService) => {
    return {
      secret: configService.get('JWT_SECRET', 'test123456'),
      signOptions: {
        expiresIn: configService.get<string>('JWT_EXPIRATION_TIME', '4h')
        //全局配置的过期时间   jwtService.sign() 方法内直接指定 expiresIn 来覆盖全局配置的过期时间
      }
    }
  }
})

@Module({
  imports: [
    ConfigModule.forRoot({ isGlobal: true, envFilePath: [envConfig.path] }),
    // ConfigModule.forRoot({ isGlobal: true }),
    TypeOrmModule.forRootAsync({
      inject: [ConfigService],
      useFactory: async (configService: ConfigService) => ({
        type: 'mysql',
        host: configService.get('DB_HOST', 'localhost'),
        port: configService.get<number>('DB_PORT', 3306),
        username: configService.get('DB_USERNAME', 'root'),
        password: configService.get('DB_PASSWORD', 'jx159357'),
        database: configService.get('DB_DATABASE', 'admin'),
        logging: false,
        timezone: '+08:00', //服务器上配置的时区
        synchronize: true, //根据实体自动创建数据库表， 生产环境建议关闭
        autoLoadEntities: true
      })
    }),
    jwtModule,
    UserModule,
    RoleModule,
    AuthModule,
    RedisModule,
    MenuModule,
  ],
  controllers: [AppController],
  // 仅注册守卫并不会使其自动应用于任何路由。要使用已注册的守卫，
  //你需要在需要的地方（如控制器或路由级别）使用 @UseGuards() 装饰器，并传入相应标识符。
  providers: [
    AppService,
    {
      provide: 'APP_GUARD_JWT',
      useClass: JwtAuthGuard
    },
    {
      provide: 'APP_GUARD_ROLE',
      useClass: RoleGuard
    }
  ]
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(AuthMiddlewareMiddleware)
      .exclude(
        {
          path: '/auth/login',
          method: RequestMethod.POST
        },
        {
          path: '/user/create',
          method: RequestMethod.POST
        },
      )
      .forRoutes('*')
  }
}
